#include "purchaseorderdialog.h"
#include "ui_purchaseorderdialog.h"

#include <QSqlQuery>
#include <QCloseEvent>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QMessageBox>
#include <QSqlError>
#include <QDate>

PurchaseOrderDialog::PurchaseOrderDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::PurchaseOrderDialog)
{
    ui->setupUi(this);


    // 初始化UI
    ui->tblProducts->setColumnCount(8);
    ui->tblProducts->setHorizontalHeaderLabels(
        {"产品", "规格", "单位", "供货周期", "数量", "单价", "总价", "操作"});
    ui->lblExpectedArrival->setText("预期到货：-");

    //连接信号与槽
    connect(ui->cmbSupplier, &QComboBox::currentIndexChanged, this, &PurchaseOrderDialog::onSupplierChanged);
    connect(ui->cmbProcurementPlan,&QComboBox::currentIndexChanged, this, &PurchaseOrderDialog::onPlanChanged);
    connect(ui->btnAddProduct, &QPushButton::clicked, this, &PurchaseOrderDialog::onAddProductClicked);
    //初始化数据
    initData();


}

void PurchaseOrderDialog::setOrderId(int poId)
{
    currentOrderId = poId;
    setWindowTitle("采购订单详情");
    loadOrderDetails(poId);
}

PurchaseOrderDialog::~PurchaseOrderDialog()
{
    delete ui;
}

void PurchaseOrderDialog::loadOrderDetails(int poId)
{
    // 加载订单基本信息
    QSqlQuery orderQuery;
    orderQuery.prepare("SELECT supplier_id, pplan_id, order_date, "
                       "total_amount, delivery_terms, order_status "
                       "FROM PurchaseOrder WHERE po_id = :poId");
    orderQuery.bindValue(":poId", poId);

    if (!orderQuery.exec() || !orderQuery.next())
    {
        QMessageBox::critical(this, "错误", "加载订单失败: " + orderQuery.lastError().text());
        reject();
        return;
    }

    // 设置供应商和采购计划
    int supplierId = orderQuery.value(0).toInt();
    int planId = orderQuery.value(1).toInt();

    // 选择供应商
    int idx = ui->cmbSupplier->findData(supplierId);
    if (idx >= 0)
    {
        ui->cmbSupplier->setCurrentIndex(idx);
        ui->cmbSupplier->setEnabled(false); // 禁用编辑
    }

    // 选择采购计划
    idx = ui->cmbProcurementPlan->findData(planId);
    if (idx >= 0)
    {
        ui->cmbProcurementPlan->setCurrentIndex(idx);
        ui->cmbProcurementPlan->setEnabled(false); // 禁用编辑
    }

    // 设置其他信息
    ui->lblTotalAmount->setText(QString("总金额：¥%1").arg(orderQuery.value(3).toDouble(), 0, 'f', 2));

    ui->lePurchaseOrder->setText(QString::number(poId));
    ui->lePurchaseOrder->setReadOnly(true);

    // 加载订单明细
    QSqlQuery detailQuery;
    detailQuery.prepare("SELECT pod.podetail_id, sp.supplier_product_id, "
                        "pod.quantity, pod.unit_price, "
                        "p.name, p.spec, p.unit, sp.delivery_days "
                        "FROM PurchaseOrderDetail pod "
                        "JOIN SupplierProduct sp ON pod.supplier_product_id = sp.supplier_product_id "
                        "JOIN Product p ON sp.product_id = p.product_id "
                        "WHERE pod.po_id = :poId");
    detailQuery.bindValue(":poId", poId);

    if (!detailQuery.exec())
    {
        QMessageBox::critical(this, "错误", "加载订单明细失败: " + detailQuery.lastError().text());
        return;
    }

    // 清空现有产品行
    ui->tblProducts->setRowCount(0);

    // 添加产品行
    while (detailQuery.next())
    {
        int row = ui->tblProducts->rowCount();
        ui->tblProducts->insertRow(row);

        // 创建只读项
        ui->tblProducts->setItem(row, 0, new QTableWidgetItem(detailQuery.value(4).toString())); // 产品名
        ui->tblProducts->setItem(row, 1, new QTableWidgetItem(detailQuery.value(5).toString())); // 规格
        ui->tblProducts->setItem(row, 2, new QTableWidgetItem(detailQuery.value(6).toString())); // 单位
        ui->tblProducts->setItem(row, 3, new QTableWidgetItem(QString("%1 天").arg(detailQuery.value(7).toInt()))); // 供货周期
        ui->tblProducts->setItem(row, 4, new QTableWidgetItem(detailQuery.value(2).toString())); // 数量
        ui->tblProducts->setItem(row, 5, new QTableWidgetItem(QString::number(detailQuery.value(3).toDouble(), 'f', 2))); // 单价
        ui->tblProducts->setItem(row, 6, new QTableWidgetItem(
                                             QString::number(detailQuery.value(2).toInt() * detailQuery.value(3).toDouble(), 'f', 2))); // 总价

        // 设置所有单元格为只读
        for (int col = 0; col < ui->tblProducts->columnCount(); col++)
        {
            QTableWidgetItem *item = ui->tblProducts->item(row, col);
            if (item)
            {
                item->setFlags(item->flags() & ~Qt::ItemIsEditable);
            }
        }

        // 隐藏操作列
        if (ui->tblProducts->columnCount() > 7)
        {
            ui->tblProducts->setItem(row, 7, new QTableWidgetItem(""));
            ui->tblProducts->item(row, 7)->setFlags(Qt::NoItemFlags);
        }
    }

    // 禁用添加按钮和表格编辑
    ui->btnAddProduct->setEnabled(false);
    ui->tblProducts->setEnabled(false);
    ui->buttonBox->setEnabled(false);

    // 计算预算信息
    calculateTotals();

    // 更新预期到货日期
    updateExpectedArrival();
}

void PurchaseOrderDialog::initData()
{
    //加载供应商
    QSqlQuery SupplierQuery("SELECT supplier_id ,name FROM Supplier");
    ui->cmbSupplier->addItem("--选择供应商--", -1);
    while (SupplierQuery.next())
    {
        int id =SupplierQuery.value(0).toInt();
        ui->cmbSupplier->addItem(SupplierQuery.value(1).toString(), id);
        // 创建供应商对象并建立映射
        supplierMap[id]={id,SupplierQuery.value(1).toString()};

    }
    // 加载已批准采购计划
    QSqlQuery planQry("SELECT pplan_id, budget FROM ProcurementPlan "
                      "WHERE approval_status = '已批准'");
    ui->cmbProcurementPlan->addItem("--选择采购计划--",-1);
    while (planQry.next())
    {
        int id = planQry.value(0).toInt();
        ui->cmbProcurementPlan->addItem(QString("计划#%1").arg(id), id);
         // 创建采购计划对象并建立映射
        planMap[id] = ProcurementPlan{id, planQry.value(1).toDouble()};
    }

    // 初始状态
    ui->tblProducts->setRowCount(0);
    ui->cmbSupplier->setCurrentIndex(0);
    ui->cmbProcurementPlan->setCurrentIndex(0);
    clearProductTable();

}

void PurchaseOrderDialog::clearProductTable()
{
    ui->tblProducts->setRowCount(0);
    calculateTotals();
    updateExpectedArrival();
}

void PurchaseOrderDialog::calculateTotals()
{
    double orderTotal =0.0;
    //计算总金额
    for (int row=0;row<ui->tblProducts->rowCount();row++)
    {
        QSpinBox *spnQuantity = qobject_cast<QSpinBox*>(ui->tblProducts->cellWidget(row, 4));
        QDoubleSpinBox *spnPrice =qobject_cast<QDoubleSpinBox*>(ui->tblProducts->cellWidget(row, 5));

        double total = 0.00;
        if (spnQuantity && spnPrice)
        {
            int quantity = spnQuantity->value();
            double price = spnPrice->value();
            total = quantity * price;

            ui->tblProducts->item(row,6)->setText(QString::number(total, 'f', 2));
            orderTotal+=total;
        }
        else if (currentOrderId != -1) //详情模式
        {
            QTableWidgetItem *totalItem = ui->tblProducts->item(row, 6);
            if (totalItem)
            {
                total = totalItem->text().toDouble();
                orderTotal+=total;
            }
        }
    }
    //显示订单总价
    ui->lblTotalAmount->setText(QString("总金额：¥%1").arg(orderTotal, 0, 'f', 2));

    //计算预算
    if (ui->cmbProcurementPlan->currentIndex()>0)
    {
        int planId = ui->cmbProcurementPlan->currentData().toInt();
        double budget = planMap[planId].budget;

        //获取已关联订单总额
        QSqlQuery query;
        query.prepare("SELECT COALESCE(SUM(total_amount), 0) "
                      "FROM PurchaseOrder "
                      "WHERE pplan_id = :planId");
        query.bindValue(":planId", planId);
        // SQL 查询是否执行成功，并且是否能获取到有效的查询结果
        if (!query.exec() || !query.next())
            return;
        double usedBudget = query.value(0).toDouble();

        double balance = 0.00;
        if (currentOrderId != -1)
        {//详情模式
            balance = budget - usedBudget;
        }
        else
        {//编辑模式
            balance = budget - usedBudget - orderTotal;
        }

        //显示预算信息
        ui->lblBudgetBalance->setText(QString("预算余额：¥%1").arg(balance, 0, 'f', 2));
        ui->lblBudgetTotal->setText(QString("(预算总额：¥%1)").arg(budget, 0, 'f', 2));

        //预算不足警告
        if (balance < 0)
        {
            ui->lblBudgetBalance->setStyleSheet("color: red; font-weight: bold;");
        }
        else
        {
            ui->lblBudgetBalance->setStyleSheet("");
        }

    }
}

void PurchaseOrderDialog::updateExpectedArrival()
{
    int maxDeliveryDays = 0;
    bool hasProduct = false;
    //遍历所有产品行， 找出最大供货周期
    for (int row = 0; row < ui->tblProducts->rowCount(); row++)
    {
        QComboBox *cmbProduct = qobject_cast <QComboBox *>(ui->tblProducts->cellWidget(row, 0));
        if (cmbProduct && cmbProduct->currentIndex() > 0)
        {
            hasProduct = true;

            //获取供货周期文本
            QString deliveryText = ui->tblProducts->item(row, 3)->text();
            if (deliveryText.endsWith("天"))
                deliveryText.chop(2);//移除天
            int days = deliveryText.toInt();
            if (days > maxDeliveryDays)
                maxDeliveryDays = days;
        }
        else if (currentOrderId != -1)
        {
            hasProduct = true;
            QTableWidgetItem *deliveryItem = ui->tblProducts->item(row, 3);
            QString deliveryText = deliveryItem->text();
            if (deliveryText.endsWith("天"))
                deliveryText.chop(2);//移除天
            int days = deliveryText.toInt();
            if (days > maxDeliveryDays)
                maxDeliveryDays = days;
        }
    }
    //更新ui显示
    if (hasProduct && maxDeliveryDays > 0)
    {
        QDate expectedDate = QDate::currentDate().addDays(maxDeliveryDays);
        ui->lblExpectedArrival->setText(
            QString("预期到货：%1").arg(expectedDate.toString("yyyy-MM-dd"))
            );
    }
    else
    {
        ui->lblExpectedArrival->setText("预期到货：-");
    }
}

void PurchaseOrderDialog::closeEvent(QCloseEvent *event)
{
    //发送关闭信号
    emit poDialogClosed();
    //接受关闭事件
    event->accept();
}
void PurchaseOrderDialog::on_buttonBox_accepted()
{
    //执行确认操作

    //数据验证
    if (ui->cmbSupplier->currentIndex() <= 0)
    {
        QMessageBox::warning(this, "保存失败", "请选择供应商");
        return;
    }

    if (ui->cmbProcurementPlan->currentIndex() <= 0)
    {
        QMessageBox::warning(this, "保存失败", "请选择采购计划");
        return;
    }
    if (ui->tblProducts->rowCount() == 0)
    {
        QMessageBox::warning(this, "保存失败", "请添加至少一个产品");
        return;
    }

    // 检查预算余额
    if (ui->lblBudgetBalance->styleSheet().contains("color: red"))
    {
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "预算不足", "预算不足, 是否继续保存订单？", QMessageBox::Yes | QMessageBox::No);
        if (reply == QMessageBox::No) return;
    }

    //开始事务
    QSqlDatabase::database().transaction();
    try
    {
        //插入订单主表
        QSqlQuery poQuery;
        poQuery.prepare(
            "INSERT INTO PurchaseOrder ("
            "   po_id, supplier_id, pplan_id, order_date, total_amount, "
            "   delivery_terms, order_status"
            ") VALUES ("
            "   :po_id, :supplier_id, :pplan_id, :order_date, :total_amount, "
            "   :delivery_terms, :order_status"
            ")"
            );
        // 从控件获取订单号
        int poId = ui->lePurchaseOrder->text().toInt();
        //获取订单总额
        QString totalText = ui->lblTotalAmount->text();
        totalText.replace("总金额：¥", "");
        double totalAmount = totalText.toDouble();

        //绑定参数
        poQuery.bindValue(":po_id", poId);
        poQuery.bindValue(":supplier_id", ui->cmbSupplier->currentData());
        poQuery.bindValue(":pplan_id", ui->cmbProcurementPlan->currentData());
        poQuery.bindValue(":order_date", QDate::currentDate());
        poQuery.bindValue(":total_amount", totalAmount);
        poQuery.bindValue(":delivery_terms", "标准交货条款");
        poQuery.bindValue(":order_status", "待处理");

        if (!poQuery.exec()) {
            throw std::runtime_error(
                "采购订单保存失败: " + poQuery.lastError().text().toStdString()
                );
        }

        //插入采购订单明细
        for (int row = 0; row < ui->tblProducts->rowCount(); row++)
        {
            QComboBox *cmbProduct = qobject_cast<QComboBox*>(ui->tblProducts->cellWidget(row, 0));
            QSpinBox *spnQuantity = qobject_cast<QSpinBox*>(ui->tblProducts->cellWidget(row, 4));
            QDoubleSpinBox *spnPrice = qobject_cast<QDoubleSpinBox*>(ui->tblProducts->cellWidget(row, 5));

            if (!cmbProduct || !spnQuantity || !spnPrice) continue;

            QSqlQuery detailQuery;
            detailQuery.prepare(
                "INSERT INTO PurchaseOrderDetail ("
                "   supplier_product_id, po_id, quantity, unit_price"
                ") VALUES ("
                "   :supplier_product_id, :po_id, :quantity, :unit_price"
                ")"
                );

            detailQuery.bindValue(":supplier_product_id", cmbProduct->currentData());
            detailQuery.bindValue(":po_id", poId);
            detailQuery.bindValue(":quantity", spnQuantity->value());
            detailQuery.bindValue(":unit_price", spnPrice->value());

            if (!detailQuery.exec()) {
                throw std::runtime_error(
                    "采购明细保存失败: " + detailQuery.lastError().text().toStdString()
                    );
            }
        }

        //插入采购履约
        QSqlQuery fulfillmentQuery;
        fulfillmentQuery.prepare(
            "INSERT INTO PurchaseFulfillment ("
            "   po_id, eta, ship_status"
            ") VALUES ("
            "   :po_id, :eta, :ship_status"
            ")"
            );

        //解析预期到货日期
        QDate etaDate = QDate::fromString(
            ui->lblExpectedArrival->text().split("：").last(),
            "yyyy-MM-dd"
            );

        fulfillmentQuery.bindValue(":po_id", poId);
        fulfillmentQuery.bindValue(":eta", etaDate);
        fulfillmentQuery.bindValue(":ship_status", "待发货");

        if(!fulfillmentQuery.exec())
        {
            throw std::runtime_error(
                "履约记录保存失败：" + fulfillmentQuery.lastError().text().toStdString()
                );
        }

        //提交事务
        QSqlDatabase::database().commit();

        QMessageBox::information(this, "保存成功", QString("采购订单 #%1 已成功创建").arg(poId));

    }catch (const std::exception& e){
        //滚回事务并显示错误
        QSqlDatabase::database().rollback();
        QMessageBox::critical(this, "数据库错误", e.what());
    }
    //发送关闭信号
    emit poDialogClosed();

    //关闭对话框并返回accepted状态
    accept();
}

void PurchaseOrderDialog::on_buttonBox_rejected()
{
    //发送关闭信号
    emit poDialogClosed();

    //关闭对话框并返回reject状态
    reject();
}

void PurchaseOrderDialog::onSupplierChanged(int index)
{
    if (index <= 0)
    {
        clearProductTable();
        return;
    }

    int supplierId = ui->cmbSupplier->currentData().toInt();

    //清空产品表格
    clearProductTable();

    //如果缓存中没有该产品，加载供应商产品
    if (!supplierProducts.contains(supplierId))
    {
        QSqlQuery query;
        query.prepare("SELECT sp.supplier_product_id, p.product_id, p.name, p.spec, p.unit, "
                      "sp.agreed_price, sp.delivery_days "
                      "FROM SupplierProduct sp "
                      "JOIN Product p ON p.product_id = sp.product_id "
                      "WHERE sp.supplier_id = :supplierId");
        query.bindValue(":supplierId", supplierId);

        if(!query.exec())
        {
            QMessageBox::critical(this, "数据库错误",
                                  "加载供应商产品失败: " + query.lastError().text());
            return;
        }

        QList<SupplierProduct> products;
        while (query.next())
        {
            SupplierProduct sp;
            sp.id = query.value(0).toInt();
            sp.productId = query.value(1).toInt();
            sp.name = query.value(2).toString();
            sp.spec = query.value(3).toString();
            sp.unit = query.value(4).toString();
            sp.agreed_price = query.value(5).toDouble();
            sp.delivery_days = query.value(6).toInt();
            products.append(sp);
        }
        supplierProducts[supplierId] = products;
    }
}

void PurchaseOrderDialog::onPlanChanged(int index)
{
    if (index <= 0)
    {
        ui->lblBudgetBalance->setText("预算余额：¥0.00");
        ui->lblBudgetTotal->setText("(预算总额：¥0.00)");
        return;
    }
    clearProductTable();
}

void PurchaseOrderDialog::onQuantityChanged()
{
    calculateTotals();
}

void PurchaseOrderDialog::onAddProductClicked()
{
    if (ui->cmbSupplier->currentIndex() <= 0)
    {
        QMessageBox::warning(this, "警告", "请先选择供应商");
        return;
    }
    if (ui->cmbProcurementPlan->currentIndex() <=0)
    {
        QMessageBox::warning(this, "警告", "请先选择采购计划");
        return;
    }
    int row = ui->tblProducts->rowCount();
    ui->tblProducts->insertRow(row);

    int supplierId = ui->cmbSupplier->currentData().toInt();
    const auto& products = supplierProducts[supplierId];

    //产品下拉框
    QComboBox *cmbProduct = new QComboBox();
    cmbProduct->addItem("--选择产品--", -1);
    for (const auto& sp : products)
    {
        cmbProduct->addItem(sp.name, sp.id);
    }

    //数量输入
    QSpinBox *spnQuantity = new QSpinBox();
    spnQuantity->setMinimum(1);
    spnQuantity->setMaximum(9999);
    spnQuantity->setValue(1);
    connect(spnQuantity, &QSpinBox::valueChanged, this, &PurchaseOrderDialog::onQuantityChanged);

    //单价输入
    QDoubleSpinBox *spnPrice = new QDoubleSpinBox();
    spnPrice->setMinimum(0.00);
    spnPrice->setMaximum(9999.99);
    spnPrice->setDecimals(2);
    connect(spnPrice, &QDoubleSpinBox::valueChanged, this, &PurchaseOrderDialog::onQuantityChanged);

    //添加删除按钮
    QPushButton *btnDelete = new QPushButton("删除");
    btnDelete->setProperty("row", row);
    connect(btnDelete, &QPushButton::clicked, this, [this, row](){
        this->deleteProductRow(row);
    });

    //初始值
    ui->tblProducts->setCellWidget(row, 0, cmbProduct);

    // 规格列（第1列）
    QTableWidgetItem *specItem = new QTableWidgetItem("");
    specItem->setFlags(specItem->flags() & ~Qt::ItemIsEditable);
    ui->tblProducts->setItem(row, 1, specItem);

    // 单位列（第2列）
    QTableWidgetItem *unitItem = new QTableWidgetItem("");
    unitItem->setFlags(unitItem->flags() & ~Qt::ItemIsEditable);
    ui->tblProducts->setItem(row, 2, unitItem);

    // 供货周期列（第3列）
    QTableWidgetItem *deliveryItem = new QTableWidgetItem("");
    deliveryItem->setFlags(deliveryItem->flags() & ~Qt::ItemIsEditable);
    ui->tblProducts->setItem(row, 3, deliveryItem);

    ui->tblProducts->setCellWidget(row, 4, spnQuantity);
    ui->tblProducts->setCellWidget(row, 5, spnPrice);

    // 总价列（第6列）
    QTableWidgetItem *totalItem = new QTableWidgetItem("0.00");
    totalItem->setFlags(totalItem->flags() & ~Qt::ItemIsEditable);
    ui->tblProducts->setItem(row, 6, totalItem);

    ui->tblProducts->setCellWidget(row, 7, btnDelete);

    //连接产品选择变化
    connect(cmbProduct, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index){

        if (index <= 0)
        {
            ui->tblProducts->item(row, 1)->setText("");
            ui->tblProducts->item(row, 2)->setText("");
            ui->tblProducts->item(row, 3)->setText("");
            spnPrice->setValue(0.00);
            return;
        }

        int spId = cmbProduct->currentData().toInt();

        for (int r = 0; r < ui->tblProducts->rowCount(); r++) {
            if (r == row) continue; // 跳过当前行
            QComboBox *otherCombo = qobject_cast<QComboBox*>(ui->tblProducts->cellWidget(r, 0));
            if (otherCombo && otherCombo->currentIndex() > 0) {
                int otherSpId = otherCombo->currentData().toInt();
                if (otherSpId == spId) {
                    QMessageBox::warning(this, "重复产品",
                                         "该产品已存在于采购订单中，不能重复添加");
                    cmbProduct->setCurrentIndex(0);
                    return;
                }
            }
        }

        auto it = std::find_if(products.begin(), products.end(),
                               [spId](const SupplierProduct & sp){
                                   return sp.id == spId;
                                });

        if (it != products.end()){
            ui->tblProducts->item(row, 1)->setText(it->spec);
            ui->tblProducts->item(row, 2)->setText(it->unit);
            ui->tblProducts->item(row, 3)->setText(QString("%1 天").arg(it->delivery_days));
            spnPrice->setValue(it->agreed_price);
        }

        calculateTotals();
        updateExpectedArrival();
    });
}

void PurchaseOrderDialog::deleteProductRow(int row)
{
    if (row >= 0 && row < ui->tblProducts->rowCount())
    {
        //删除行
        ui->tblProducts->removeRow(row);

        //更新所有后续行
        for (int r = row; r < ui->tblProducts->rowCount();r++)
        {
            QPushButton *btn = qobject_cast<QPushButton*>(ui->tblProducts->cellWidget(r, 7));
            if (btn)
            {
                btn->setProperty("row", r);
            }
        }
        calculateTotals();
        updateExpectedArrival();
    }
}
